package first.endtoend

import first.endtoend.messages.MessageCode
import grails.converters.JSON
import org.springframework.dao.DataIntegrityViolationException

class TraceController
{

    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

    def categoryTraceService

    def getAllTraces()
    {
        if (Trace.findAll() != null)
        {
            render([status: true, traces: Trace.findAll(), tracesCount: Trace.findAll().size()] as JSON)
        } else
        {
            render([status: false, code: MessageCode.NULL_RESPONSE.value()] as JSON)
        }

    }

    /*
    this method render traces by filtering  an agent
     */

    def filterByAgent()
    {
        print("*** HERE idAgent :" + params.id)
        def agent = (Agent) User.findById(params.id)

        if (agent)
        {
            if (agent.traces)
            {
                print("traces exists for this agent!")
                render([status: true, traces: agent.traces, code: MessageCode.SUCCESS, tracesCount: agent.traces.size()] as JSON)
            } else
            {
                print("there is no traces")
                render([status: false, code: MessageCode.NULL_RESPONSE.value()] as JSON)
            }
        } else
        {
            render([status: false, code: MessageCode.NOT_FOUND.value()] as JSON)
        }
        println(agent.traces.toString())
    }

    /*
   this method render traces by filtering  a category
   */

    def filterByCategory()
    {
        def category = Category.findById(params.id)
        //find traces from category
        // 1) try to find all families related to this category
        // 2) get all tags of these families
        // 3) render requested traces


        if (category)
        {
            if (category.families)
            {

                render(categoryTraceService.toJson(category) as JSON)


            } else
            {//no families for this category
                render([status: false, code: MessageCode.NULL_RESPONSE.value()] as JSON)

            }
        } else
        {
            render([status: false, code: MessageCode.NULL_RESPONSE.value()] as JSON)
        }


    }

    /*
    this method render traces by filtering  an agent and period
     */
    /*  def filterByAgentAnPeriod(Agent anAgent, Date start, Date end){
          List<Trace> result = new ArrayList<Trace>()
          List<Trace> traces=Trace.findByAgent(anAgent)

          traces.each {
              if(it.dateOp>=start && it.dateOp<=end){
                  println(it.toString())
                  result.add(it)
              }
          }
          return result
      }*/


    def index()
    {
        redirect(action: "list", params: params)
    }

    def list(Integer max)
    {
        params.max = Math.min(max ?: 10, 100)
        [traceInstanceList: Trace.list(params), traceInstanceTotal: Trace.count()]
    }

    def create()
    {
        [traceInstance: new Trace(params)]
    }

    def save()
    {
        def traceInstance = new Trace(params)
        if (!traceInstance.save(flush: true))
        {
            render(view: "create", model: [traceInstance: traceInstance])
            return
        }

        flash.message = message(code: 'default.created.message', args: [message(code: 'trace.label', default: 'Trace'), traceInstance.id])
        redirect(action: "show", id: traceInstance.id)
    }

    def show(Long id)
    {
        def traceInstance = Trace.get(id)
        if (!traceInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'trace.label', default: 'Trace'), id])
            redirect(action: "list")
            return
        }

        [traceInstance: traceInstance, pathPhoto: traceInstance.pathPhoto]
    }

    def edit(Long id)
    {
        def traceInstance = Trace.get(id)
        if (!traceInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'trace.label', default: 'Trace'), id])
            redirect(action: "list")
            return
        }

        [traceInstance: traceInstance]
    }

    def update(Long id, Long version)
    {
        def traceInstance = Trace.get(id)
        if (!traceInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'trace.label', default: 'Trace'), id])
            redirect(action: "list")
            return
        }

        if (version != null)
        {
            if (traceInstance.version > version)
            {
                traceInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
                        [message(code: 'trace.label', default: 'Trace')] as Object[],
                        "Another user has updated this Trace while you were editing")
                render(view: "edit", model: [traceInstance: traceInstance])
                return
            }
        }

        traceInstance.properties = params

        if (!traceInstance.save(flush: true))
        {
            render(view: "edit", model: [traceInstance: traceInstance])
            return
        }

        flash.message = message(code: 'default.updated.message', args: [message(code: 'trace.label', default: 'Trace'), traceInstance.id])
        redirect(action: "show", id: traceInstance.id)
    }

    def delete(Long id)
    {
        def traceInstance = Trace.get(id)
        if (!traceInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'trace.label', default: 'Trace'), id])
            redirect(action: "list")
            return
        }

        try
        {
            traceInstance.delete(flush: true)
            flash.message = message(code: 'default.deleted.message', args: [message(code: 'trace.label', default: 'Trace'), id])
            redirect(action: "list")
        }
        catch (DataIntegrityViolationException e)
        {
            flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'trace.label', default: 'Trace'), id])
            redirect(action: "show", id: id)
        }
    }

    /**
     * Get all traces for a given level
     * @param idLevel Id level
     * @return an arrayList of all traces of a level
     */
    def getTracesByLevel()
    {
        Level level = Level.findById(params.idLevel)
        println "\n_______________________\nLevel = " + level.toString()
        ArrayList<Level> levels = new ArrayList<Level>()
        ArrayList<Locality> localities = new ArrayList<Locality>()
        ArrayList<Address> addresses = new ArrayList<Address>()
        ArrayList<Trace> agents = new ArrayList<Agent>()
        ArrayList<Trace> traces = new ArrayList<Trace>()

        for (Level l : level.getAllChildrenLevel(level, levels))
        {
            localities.addAll(Locality.findAllByLevel(l))
        }
        for (Locality locality : localities)
        {
            addresses.addAll(Address.findAllByLocality(locality))
        }
        for (Address address : addresses)
        {
            agents.addAll(Agent.findAllByAddress(address))
        }
        for (Agent agent : agents)
        {
            traces.addAll(Trace.findAllByAgent(agent))
        }
        println "traces = " + traces.size()
        [traceInstance: traces]
    }

    public def getTracesByAgent()
    {
        println "\n_______________________\nAgents = " + Agent.findById(params.idAgent)
        def traces = Trace.findAllByAgent(Agent.findById(params.idAgent))
        println "traces = " + traces.size()
        [traceInstance: traces]

    }

    public def getTracesByCategory()
    {
        println "\n_______________________\nCategory = " + Category.findById(params.idCategory)
        def category = Category.findById(params.idCategory)
        def families = Family.findAllByCategory(category)
        def traces = []
        for (Family family : families)
        {
            traces.addAll(Trace.findAllByFamily(family))
        }
        println "traces = " + traces.size()
        [traceInstance: traces]
    }

}
